package io.gitee.kotle.android.view

import android.content.Context
import android.util.AttributeSet
import android.util.SparseArray
import android.view.View
import android.widget.ImageView
import androidx.annotation.DrawableRes
import androidx.core.graphics.drawable.toBitmap
import androidx.core.util.containsValue
import androidx.core.view.children
import androidx.lifecycle.lifecycleScope
import coil.request.ImageRequest
import io.gitee.kotle.android.BaseGlobalConst
import io.gitee.kotle.android.utils.*
import io.gitee.kotle.android.widget.BaseFrameLayout
import kotlinx.coroutines.launch

open class NineImageLayout : BaseFrameLayout {
    private val tempViews = SparseArray<View>()

    /**
     * 横向间隔
     */
    var horizontalSpace = dip(4)

    /**
     * 竖向间隔
     */
    var verticalSpace = horizontalSpace

    /**
     * 每行最多几个子view
     */
    var maxPerLine = 3

    /**
     * 只有一个子view，支持自由布局
     * true，可以根据 图片尺寸，更改长宽
     * false：按照九宫格方式布局
     */
    var oneViewFreeLayout = true

    /**
     * 图片加载的占位图
     */
    @DrawableRes
    var placeholderRes: Int? = null

    /**
     * 创建子view的监听
     */
    var onCreateViewListener: Function1<Context, View>? = null

    /**
     * 子view点击监听
     */
    var onViewClickListener: Function3<View, MutableList<String>, Int, Unit>? = null

    /**
     * 绑定数据的监听
     */
    var onBindViewListener: Function4<View, MutableList<String>, String, Int, Unit>? = null

    constructor(context: Context) : super(context)
    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    )

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        val count = childCount
        if (count == 0) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec)
            return
        }
        if (!oneViewFreeLayout || childCount > 1) {
//            val widthMode = MeasureSpec.getMode(widthMeasureSpec)
//            val heightMode = MeasureSpec.getMode(heightMeasureSpec)
            val widthSize = MeasureSpec.getSize(widthMeasureSpec)
//            val heightSize = MeasureSpec.getSize(heightMeasureSpec)
            val sideLength = getSideLength(widthSize)
            //总行数，从0开始
            val numberOfLines = (childCount - 1) / maxPerLine
            val newHeight = numberOfLines * (sideLength + verticalSpace) + sideLength
            setMeasuredDimension(widthSize, newHeight)
        } else {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        }
    }

    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        if (changed) {
            when (childCount) {
                1 -> {
                    if (oneViewFreeLayout) {
                        val view = getChildAt(0)
                        view.layout(0, 0, view.measuredWidth, view.measuredHeight)
                    } else {
                        layoutChild(l, t, r, b)
                    }
                }
                else -> {
                    layoutChild(l, t, r, b)
                }
            }
        }
    }

    private fun layoutChild(l: Int, t: Int, r: Int, b: Int) {
        children.forEachIndexed { index, view ->
            //行数 从0开始
            val numberOfLines = (index / maxPerLine)
            //列数 从0开始
            val numberOfColumns = index % maxPerLine
            //计算view的宽高
            val sideLength = getSideLength(r - l)
            val left = numberOfColumns * (sideLength + horizontalSpace)
            val top = numberOfLines * (sideLength + verticalSpace)
            val right = left + sideLength
            val bottom = top + sideLength
            view.layout(left, top, right, bottom)
        }
    }

    /**
     * 获取view的平均宽度
     */
    private fun getSideLength(width: Int): Int {
        return (width - horizontalSpace * (maxPerLine - 1)) / maxPerLine
    }

    /**
     * 如果不拦截view，
     */
    private var _datas: MutableList<String>? = null
    fun setDatas(
        datas: MutableList<String>?,
        ivOneWidth: Int = 0,
        ivOneHeight: Int = 0,
        maxOneWidth: Int = 0,
        maxOneHeight: Int = 0
    ) {
        this._datas = datas
        if (datas.isNullOrEmpty()) {
            removeAllViews()
        } else {
            if (childCount > datas.count()) {
                val size = childCount - datas.count()
                removeViews(datas.count(), size)
            }
            when (datas.count()) {
                1 -> {
                    if (oneViewFreeLayout) {
                        setOneView(
                            ivOneWidth,
                            ivOneHeight,
                            maxOneWidth,
                            maxOneHeight
                        )
                    } else {
                        setOtherView()
                    }
                }
                else -> {
                    setOtherView()
                }
            }
        }
    }

    private fun setOtherView() {
        val datas = _datas ?: return
        val count = childCount
        datas.forEachIndexed { index, data ->
            val view = getView(index, count)
            val listener = onBindViewListener
            if (listener == null) {
                view.asOrNull<ImageView>()?.setImageByCoil(data) {
                    placeholderRes?.let { p ->
                        it.placeholder(p)
                    }
                }
            } else {
                listener.invoke(view, datas, data, index)
            }
            if (view.parent == null) {
                this@NineImageLayout.addView(view)
            }
        }
    }


    /**
     *  url 图片地址
     *  ivWidth 图片宽度，不知道可以不写，默认0
     *  ivHeight 图片高度，不知道可以不写，默认0
     *  maxWidth 限制图片的最大宽度
     *  maxHeight 限制图片的最大高度
     */
    private fun setOneView(
        ivWidth: Int = 0,
        ivHeight: Int = 0,
        maxWidth: Int = 0,
        maxHeight: Int = 0
    ) {
        val datas = _datas ?: return
        val url = datas.firstOrNull() ?: return
        val listener = onBindViewListener
        if (ivHeight == 0 || ivWidth == 0) {
            appCompatActivity.also {
                it.lifecycleScope.launch {
                    val bitmap = BaseGlobalConst.coilImageLoader.execute(
                        ImageRequest.Builder(it).data(url).lifecycle(it).build()
                    ).drawable?.toBitmap()
                    if (bitmap != null) {
                        val view =
                            addOneView(bitmap.width, bitmap.height, maxWidth, maxHeight)
                        if (listener == null) {
                            view.asOrNull<ImageView>()?.setImageBitmap(bitmap)
                        } else {
                            listener.invoke(view, datas, url, 0)
                        }
                    }
                }
            }
        } else {
            val view = addOneView(ivWidth, ivHeight, maxWidth, maxHeight)
            if (listener == null) {
                view.asOrNull<ImageView>()?.setImageByCoil(url) {
                    placeholderRes?.let { p ->
                        it.placeholder(p)
                    }
                }
            } else {
                listener.invoke(view, datas, url, 0)
            }
        }
    }

    /**
     * 根据参数，设置只有一张图片时候，view的显示
     */
    private fun addOneView(
        ivWidth: Int,
        ivHeight: Int,
        maxWidth: Int,
        maxHeight: Int,
    ): View {
        var viewMaxW = maxWidth
        var viewMaxH = maxHeight
        if (maxWidth == 0 || maxHeight == 0) {
            viewMaxW = dip(240)
            viewMaxH = dip(240)
        }
        //view宽高比的一个分隔值
        val viewRatio = viewMaxW / viewMaxH.toFloat()
        val view = getView(0, childCount)
        var realW = 0
        var realH = 0
        val bitmapRatio = ivWidth.toFloat() / ivHeight
        when {
            bitmapRatio <= viewRatio -> {
                //高度固定，根据图片尺寸，缩放宽度
                realH = viewMaxH
                realW = (realH * bitmapRatio).toInt()
            }
            else -> {
                //宽度固定，根据图片尺寸，缩放高度
                realW = viewMaxH
                realH = (realW / bitmapRatio).toInt()
            }
        }
        val lp = LayoutParams(realW, realH)
        this@NineImageLayout.addView(view, lp)
        return view
    }

    /**
     * 获取缓存的view，并且添加到布局中
     */
    private fun getView(position: Int, viewCount: Int): View {
        if (position < viewCount) {
            return getChildAt(position)
        }
        var tempView: ImageView? = null
        val count = tempViews.size()
        for (index in 0 until count) {
            val value = tempViews.valueAt(index)
            if (value is ImageView && value.parent == null) {
                tempView = value
                break
            }
        }
        val view = tempView ?: createImageView().apply {
            this.onClick {
                _datas?.let {
                    onViewClickListener?.invoke(this, it, indexOfChild(this))
                }
            }
        }
        if (!tempViews.containsValue(view)) {
            tempViews.append(tempViews.size(), view)
        }
        if (view.id == NO_ID) {
            view.id = View.generateViewId()
        }
        return view
    }

    /**
     * 创建view对象
     */
    private fun createImageView(): View {
        return onCreateViewListener?.invoke(context) ?: ImageView(context)
    }
}